use std::fmt::format;
use anyhow::{Context, Result};
use serde::{Deserialize, Serialize};
use std::fs;
use dirs;
use std::path::{Path, PathBuf};
use tracing::{info, debug, warn, error, span, Level};

#[derive(Debug, Serialize , Deserialize)]
pub struct Config {
    pub global: GlobalConfig,
    pub mappings: Vec<Mapping>,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct GlobalConfig {
    pub parallel_jobs: Option<usize>,
    pub daemon_scan_interval: Option<u64>, 
}

#[derive(Debug,Serialize , Deserialize, Clone)]
pub struct Mapping {
    pub name: String,
    pub source: PathBuf,
    pub destination: PathBuf,
    pub include: Vec<String>,
    pub exclude: Vec<String>,
    pub ttl: String, // "never" 或分钟数
}

impl Config {
    pub fn load() -> Result<Self> {
        let config_path = Self::config_path()?;
        let contents = fs::read_to_string(&config_path)
            .with_context(|| format!("无法读取配置文件: {}", config_path.display()))?;
        toml::from_str(&contents).context("解析配置文件失败")
    }

    pub fn save(&self) -> anyhow::Result<()> {
        let config_path = Self::config_path()? ;
        let toml_content = toml::to_string_pretty(self)
            .context("序列化配置文件失败")? ;
        fs::write(&config_path , toml_content)
            .with_context(|| format!("写入配置文件失败:{}" , config_path.display())) ? ;
        Ok(())
    }

    pub fn config_path() -> Result<PathBuf> {
        dirs::home_dir()
            .context("无法找到用户主目录")
            .map(|home| home.join(".ice").join("config.toml"))
    }

    pub fn find_mapping_by_name(&self, name: &str) -> Option<&Mapping> {
        self.mappings.iter().find(|m| m.name == name)
    }

    pub fn find_mapping_by_current_dir(&self) -> Result<Option<&Mapping>> {
        let current_dir = std::env::current_dir()?;
        for mapping in &self.mappings {
            if current_dir.starts_with(&mapping.source) {
                return Ok(Some(mapping));
            }
        }
        Ok(None)
    }


    pub fn init_config(force: bool) -> Result<()> {

        info!("开始执行 `ice init` 命令（force模式: {}）", force);

        let config_path = Config::config_path()
            .with_context(|| "获取配置文件路径失败")?;

        debug!("配置文件目标路径: {}", config_path.display()); // debug级别：细节信息

        if config_path.exists() && !force {
            info!("init执行完毕, 配置文件已存在: {} ", config_path.display());
            // todo 目前只有延时办法可以解决日志遗漏问题  其余更优雅的办法还在寻找中
            std::thread::sleep(std::time::Duration::from_millis(100)); // 因为我们采用的是异步写日志 在退出前所以需要一定的时间写日志
            anyhow::bail!(
                "配置文件已存在: {}\n. 如需请考虑使用 --force 覆盖已存在的配置.",
                config_path.display()
            );
        }

        // 创建 ~/.ice 目录
        let ice_dir = config_path.parent()
            .with_context(|| "无法获取配置目录路径".to_string())?;
        fs::create_dir_all(ice_dir)
            .with_context(|| format!("创建 ~/.ice 目录失败:{}" , ice_dir.display()))?;
        debug!("成功创建配置文件父目录: {}", ice_dir.display());

        // 从 assets/config.toml 读取默认配置
        let default_config_bytes = include_bytes!("../assets/config.toml");
        let default_config = String::from_utf8_lossy(default_config_bytes);
        debug!("默认配置内容: \n{}", default_config);

        fs::write(&config_path, default_config.as_bytes())
            .with_context(|| format!("写入默认配置文件失败:{}" , config_path.display()))? ;
        info!("init执行完毕, 配置文件已成功写入: {}", config_path.display());
        Ok(())
    }
    
    
    pub fn has_mapping(&self, name:&str) -> bool {
        self.mappings.iter().any(|mapping| mapping.name == name) 
    }
    
    pub fn get_mapping(&self, name: &str) -> Option<&Mapping> {
        self.find_mapping_by_name(name) 
    }
    
}



